package com.share.finance.risk.rules.service.impl.exe;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONPath;
import com.share.common.utils.ThreadUtil;
import com.share.finance.risk.common.enums.ResultEnum;
import com.share.finance.risk.common.model.sys.RuleNode;
import com.share.finance.risk.common.model.sys.RuleRequest;
import com.share.finance.risk.rules.model.core.FactDrls;
import com.share.finance.risk.rules.model.db.ExecuteResult;
import com.share.finance.risk.rules.model.db.Project;
import com.share.finance.risk.rules.service.IExecuteResultService;
import com.share.finance.risk.rules.service.IProjectService;
import com.share.finance.risk.rules.service.core.ContainerService;
import com.share.finance.risk.rules.service.exe.ExecuteRuleService;
import com.share.finance.risk.rules.utils.KieUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.kie.api.io.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Slf4j
@Service
public class ExecuteRuleServiceImpl implements ExecuteRuleService {
    @Autowired
    private IProjectService iProjectService;

    @Autowired
    private IExecuteResultService iExecuteResultService;

    @Autowired
    private ContainerService containerService;

    @Override
    public RuleNode exeRule(RuleRequest req, String reqIp) {
        //出参信息
        RuleNode reRuleNode = new RuleNode();
        ExecuteResult reqLog = new ExecuteResult();
        Map<String, Object> data = new HashMap<>();

        try {
            //1.获执行版本的基本信息
            long startTime = System.currentTimeMillis();
            Project project = iProjectService.getProject(req.getProjectCode(), req.getEventCode());
            if (project == null) {
                reqLog.setErrMsg("数据产品不存在");
            } else {
                //1.事先设置projectid
                reqLog.setProjectId(project.getId());
                reqLog.setReqIp(reqIp);

                //2.查询上一次断点的执行结果
                List<String> tmpListNodeName = new LinkedList<>();
                ExecuteResult tmpResult = iExecuteResultService.queryLastDataByOrderIdAndProjectId(req.getOrderId(), project.getId());
                if (tmpResult != null && !StringUtils.isEmpty(tmpResult.getOutputData())) {
                    tmpListNodeName = (List<String>) JSONPath.eval(tmpResult.getOutputData(), "$.ruleNameList");
                    if (tmpListNodeName == null) {
                        tmpListNodeName = new LinkedList<>();
                    }
                }

                //3.组装数据
                data.put("input", req.getData()); //变量信息
                data.put("nodeList", new LinkedList<>());//执行的节点保存
                data.put("ruleNameList", tmpListNodeName);//累计的所有已执行的规则名

                //4.执行规则
                containerService.exeRule(project, data);

                //5.数据解析
                List<RuleNode> nodeList = (List<RuleNode>) data.get("nodeList");//执行的节点信息
                if (!CollectionUtils.isEmpty(nodeList)) {
                    Collections.sort(nodeList);
                    reRuleNode = nodeList.get(0);
                }

                //结果信息
                data.remove("input");//不需要存的
                reqLog.setExeStatus(dealStatus(reRuleNode));
                reqLog.setOutputData(JSON.toJSONString(data));
            }
        } catch (Exception e) {
            reqLog.setErrMsg(e.getMessage());
            reqLog.setExeStatus(ResultEnum.EXCEPTION.code);
            log.error("exeRule执行异常", e);
        } finally {
            RuleNode reRuleNodeAnsy = reRuleNode;
            ThreadUtil.execute(() -> iExecuteResultService.saveExecuteResult(req, reqLog, reRuleNodeAnsy));
        }
        return reRuleNode;
    }

    @Override
    public RuleNode test(FactDrls req) {
        RuleNode reRuleNode = new RuleNode();

        //1.组装数据
        Map<String, Object> data = new HashMap<>();
        data.put("input", req.getFacts()); //变量信息
        data.put("nodeList", new LinkedList<>());//执行的节点保存
        data.put("ruleNameList", new LinkedList<>());//累计的所有已执行的规则名

        //2.封装drls
        List<Resource> resourceList = KieUtil.drls2KieResource(req.getDrls());

        //3.执行
        containerService.test(resourceList, data);

        //4.数据解析
        List<RuleNode> nodeList = (List<RuleNode>) data.get("nodeList");//执行的节点信息
        if (!CollectionUtils.isEmpty(nodeList)) {
            Collections.sort(nodeList);
            reRuleNode = nodeList.get(0);
        }

        return reRuleNode;
    }

    private String dealStatus(RuleNode reRuleNode) {
        String reStr = null;
        if (reRuleNode == null) {
            reStr = ResultEnum.UNKNOWN.code;
        } else if (StringUtils.isNotBlank(reRuleNode.getResultType())) {
            reStr = reRuleNode.getResultType();
        } else if (StringUtils.isNotBlank(reRuleNode.getIntIds())) {
            reStr = ResultEnum.BREAKPOINT.code;
        }
        return reStr;
    }
}
